package com.example.flutter_card_plugin;
import android.app.Activity;
import android.util.Log;
import com.android.xhapimanager.XHApiManager;
import com.example.flutter_card_plugin.constant.HttpConstant;
import com.example.flutter_card_plugin.model.ComBean;
import com.example.flutter_card_plugin.utils.DeviceUtils;
import com.example.flutter_card_plugin.utils.HexToDec;
import com.example.flutter_card_plugin.utils.PunchClock;
import com.example.flutter_card_plugin.utils.SerialHelper;
import com.google.gson.Gson;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

/** FlutterCardPlugin */
public class FlutterCardPlugin implements ActivityAware, FlutterPlugin, MethodCallHandler {
  /// The MethodChannel that will the communication between Flutter and native Android
  ///
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private MethodChannel channel;

  private Result channelResult;
  //上下文
  private Activity mContext;

  //电子班牌API
  private XHApiManager apiManager;

  /*
   * 串口
   */
  private SerialControl ComA, ComD;
  /*
   * 刷新显示线程
   *
   */
  private DispQueueThread DispQueue;


  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "flutter_card_plugin");
    channel.setMethodCallHandler(this);
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    String method = call.method;
    //都以map形式传参
    Map<String, Object> map = (Map<String, Object>) call.arguments;
    switch (method) {

      case "serialNumber"://序列号
        String serialNumber= DeviceUtils.getSerialNumber();
        result.success(serialNumber);
        break;

      case "powerOff"://关机
        apiManager.XHShutDown();//关机
        break;
      case "restart"://重启
        apiManager.XHReboot();
        break;

      case "showOrHideStatusBar"://显示或隐藏状态栏
        //true显示状态栏 false关闭状态栏
        boolean status = (boolean) map.get("status");
        apiManager.XHShowOrHideStatusBar(status);
        break;

      case "installAPK"://静默安装
        //path：apk安装路径，pkgname:应用包名com.zaedu.card
        String path = (String) map.get("path");
        String pkgname = (String) map.get("pkgname");
        apiManager.XHInstallOnBackground(path,pkgname);
        break;

      case "destroy":
        ComD.close();
        ComA.close();
        break;
      default:
        break;
    }
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }

  @Override
  public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
    mContext = binding.getActivity();
    //初始化api
    apiManager = new XHApiManager();
    initSerialPort();
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {

  }

  @Override
  public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {

  }

  @Override
  public void onDetachedFromActivity() {
    //关闭
    ComD.close();
    ComA.close();
  }


  /*
   *串口初始化
   */
  private void initSerialPort() {
      //大班牌型号
      ComA = new SerialControl();
      ComD = new SerialControl();
      openSerialPortA();
      openSerialPortD();
  }


  /*
   * 开启串口
   */
  private void openSerialPortA() {
    DispQueue = new DispQueueThread();
    DispQueue.start();
    PunchClock.SetLoopData(ComA, HttpConstant.SEND_TEST_A);
    PunchClock.SetiDelayTime(ComA, HttpConstant.TIME);
    ComA.setPort(HttpConstant.PORT_ONE);
    ComA.setBaudRate(HttpConstant.BAUDRATE);
    PunchClock.OpenComPort(mContext, ComA);
  }




  private void openSerialPortD() {
    DispQueue = new DispQueueThread();
    DispQueue.start();
    PunchClock.SetLoopData(ComD, HttpConstant.SEND_TEST_D);
    PunchClock.SetiDelayTime(ComD, HttpConstant.TIME);
    ComD.setPort(HttpConstant.PORT_TWO);
    ComD.setBaudRate(HttpConstant.BAUDRATE);
    PunchClock.OpenComPort(mContext, ComD);
  }




  public class SerialControl extends SerialHelper {
    public SerialControl() {

    }

    @Override
    protected void onDataReceived(final ComBean ComRecData) {
      //数据接收量大或接收时弹出软键盘，界面会卡顿,可能和6410的显示性能有关
      //直接刷新显示，接收数据量大时，卡顿明显，但接收与显示同步。
      //用线程定时刷新显示可以获得较流畅的显示效果，但是接收数据速度快于显示速度时，显示会滞后。
      //最终效果差不多-_-，线程定时刷新稍好一些。
      DispQueue.AddQueue(ComRecData);//线程定时刷新显示(推荐)
    }
  }


  //刷新显示线程
  private class DispQueueThread extends Thread {
    private Queue<ComBean> QueueList = new LinkedList<>();

    @Override
    public void run() {
      super.run();
      while (!isInterrupted()) {
        final ComBean ComData;
        while ((ComData = QueueList.poll()) != null) {
          mContext.runOnUiThread(() -> DispRecData(ComData));
          break;
        }
        try {
          Thread.sleep(300);// 显示性能高的话，可以把此数值调小。
        } catch (Exception e) {
          e.printStackTrace();
          break;
        }
      }
    }

    public synchronized void AddQueue(ComBean ComData) {
      QueueList.add(ComData);
    }
  }






  /**
   * @param: ComBean卡片信息
   * 接受读卡显示接收数据
   */
  private void DispRecData(ComBean ComRecData) {
    try {
      //查询设备成功才可以刷卡
      if (ComRecData.bRec != null) {
        /*从第二位开始截取前4位*/
        byte[] bt = new byte[4];
        System.arraycopy(ComRecData.bRec, 2, bt, 0, 4);
        //截取AA55之后的字符
        String hex = HexToDec.bytesToHexString(bt);
        long valueTen = Long.parseLong(hex, 16);
        //卡号
        String cardNumber= String.valueOf(valueTen);
        Map<String, String> map = new HashMap<>();
        map.put("name", cardNumber);
//        Log.e("TAG","卡号"+cardNumber);
        channel.invokeMethod("slotCardCallBack", new Gson().toJson(map));
      }
    }catch (Exception e){
      Log.e("card","刷卡异常"+e.getMessage());
    }
  }

}




